package com.lnu_devteam.zongce.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lnu_devteam.zongce.common.ErrorCode;
import com.lnu_devteam.zongce.common.ResultUtils;
import com.lnu_devteam.zongce.common.TokenResponse;
import com.lnu_devteam.zongce.constant.JWTConstant;
import com.lnu_devteam.zongce.constant.UserConstant;
import com.lnu_devteam.zongce.exception.BusinessException;
import com.lnu_devteam.zongce.listener.DataListener;
import com.lnu_devteam.zongce.mapper.UserMapper;
import com.lnu_devteam.zongce.model.dto.UserChangePwdDTO;
import com.lnu_devteam.zongce.model.dto.UserDTO;
import com.lnu_devteam.zongce.model.dto.UserLoginDTO;
import com.lnu_devteam.zongce.model.entity.User;
import com.lnu_devteam.zongce.model.enums.RoleEnum;
import com.lnu_devteam.zongce.model.vo.UserVO;
import com.lnu_devteam.zongce.service.UserService;
import com.lnu_devteam.zongce.utils.FuncUtils;
import com.lnu_devteam.zongce.utils.JWTUtils;
import com.lnu_devteam.zongce.utils.Md5Utils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

/**
 * @author xbaoziplus
 * @description 针对表【tb_user(用户表)】的数据库操作Service实现
 * @createDate 2023-03-23 11:48:19
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
        implements UserService {

    @Resource
    private HttpServletRequest request;

    @Resource
    private JWTUtils jwtUtils;

    @Override
    public TokenResponse<UserVO> login(UserLoginDTO userLoginDTO, HttpServletRequest request) {
        String uAccount = userLoginDTO.getUAccount();
        String uPassword = userLoginDTO.getUPassword();
        // 数据空串校验
        FuncUtils.isTrueToThr(StringUtils.isBlank(uAccount) || StringUtils.isBlank(uPassword))
                .throwException(ErrorCode.PARAMS_ERROR);
        User user = getOne(
                new LambdaQueryWrapper<User>()
                        .eq(User::getUAccount, uAccount)
                        .eq(User::getUPassword, Md5Utils.getMd5String(uPassword))
        );
        if (user == null) {
            throw new BusinessException(ErrorCode.LOGIN_ERROR);
        }
        // 成功查询出用户，记录登录态
        //request.getSession().setAttribute(UserConstant.LOGIN_KEY, user.getUId());
        String authentication = jwtUtils.generateToken(user.getUId().toString());
        UserVO userVO = new UserVO();
        BeanUtils.copyProperties(user, userVO);
        return ResultUtils.success(userVO, authentication);
    }

    @Override
    public User getLoginUser(HttpServletRequest request) {
        String auth = request.getHeader(JWTConstant.HEAD_NAME);
        return getOne(new LambdaQueryWrapper<User>()
                //.eq(User::getUId, request.getSession().getAttribute(UserConstant.LOGIN_KEY))
                .eq(User::getUId, jwtUtils.getSubject(auth))
        );
    }

    @Override
    public User getLoginUser() {
        return this.getLoginUser(request);
    }

    @Override
    public String getLoginUserAccount() {
        String auth = request.getHeader(JWTConstant.HEAD_NAME);
        User loginUser = getOne(new LambdaQueryWrapper<User>()
                        .select(User::getUAccount)
                //.eq(User::getUId, request.getSession().getAttribute(UserConstant.LOGIN_KEY))
                .eq(User::getUId, jwtUtils.getSubject(auth))
        );
        if (loginUser == null || StringUtils.isBlank(loginUser.getUAccount())) {
            throw new BusinessException(ErrorCode.VERIFY_ERROR);
        }
        return loginUser.getUAccount();
    }

    @Override
    public Long addUser(UserDTO userDTO) {
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        // 密码为默认前缀+学号/工号
        user.setUPassword(
                Md5Utils.getMd5String(UserConstant.DEFAULT_PWD_PRE + user.getUAccount())
        );
        boolean isSuccess = save(user);
        if (!isSuccess) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR);
        }
        return user.getUId();
    }

    @Override
    public boolean changePwd(UserChangePwdDTO userChangePwdDTO, HttpServletRequest request) {
        User loginUser = getLoginUser(request);
        // 只允许自己修改
        if (!loginUser.getUId().equals(userChangePwdDTO.getUId())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        // 校验密码是否匹配
        String oldPwd = userChangePwdDTO.getOldPwd();
        String newPwd = userChangePwdDTO.getNewPwd();
        if (StringUtils.isBlank(oldPwd) || StringUtils.isBlank(newPwd)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (!loginUser.getUPassword().equals(Md5Utils.getMd5String(oldPwd))) {
            throw new BusinessException(ErrorCode.PASSWORD_NOT_FORMAT);
        }
        if (oldPwd.equals(newPwd)) {
            throw new BusinessException(ErrorCode.PASSWORD_NOT_CHANGE);
        }
        // 修改密码
        return update(new LambdaUpdateWrapper<User>()
                .set(User::getUPassword, Md5Utils.getMd5String(newPwd))
                .eq(User::getUId, loginUser.getUId()));
    }

    @Override
    public boolean isAdmin(User user) {
        return user.getUAuth().equals(RoleEnum.ADMIN.getAuth()) || user.getUAuth().equals(RoleEnum.SUPER.getAuth());
    }

    @Override
    public boolean resetPwd(Long targetId, HttpServletRequest request) {
        if (targetId == null || targetId <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        User targetUser = getOne(
                new LambdaQueryWrapper<User>()
                        .select(User::getUId, User::getUAccount, User::getUPassword)
                        .eq(User::getUId, targetId)
        );
        if (targetUser == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        // 重置密码为默认前缀+学号/工号
        targetUser.setUPassword(
                Md5Utils.getMd5String(UserConstant.DEFAULT_PWD_PRE + targetUser.getUAccount())
        );
        return updateById(targetUser);
    }

    @Override
    public boolean upload(MultipartFile file) {
        // 获得上传文件的名称
        String filename = file.getOriginalFilename();
        if (StringUtils.isBlank(filename)) {
            throw new BusinessException(ErrorCode.UPLOAD_ERROR.getCode(), ErrorCode.UPLOAD_ERROR.getMessage() + ", 文件名不能为空");
        }
        // 获取源文件的后缀名
        int index = filename.lastIndexOf(".");
        // 对没有后缀名的文件进行判断
        if (index < 0) {
            throw new BusinessException(ErrorCode.UPLOAD_ERROR.getCode(), ErrorCode.UPLOAD_ERROR.getMessage() + ", 只支持Excel文件");
        }
        // 截取.点后面的内容，即后缀名
        String suffix = filename.substring(index + 1);
        //判断是否为excel文档
        if (!"xlsx".equals(suffix) && !"xls".equals(suffix)) {
            throw new BusinessException(ErrorCode.UPLOAD_ERROR.getCode(), ErrorCode.UPLOAD_ERROR.getMessage() + ", 只支持Excel文件");
        }
        try {
            EasyExcel.read(file.getInputStream(), User.class, new DataListener(this)).sheet().doRead();
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(ErrorCode.UPLOAD_ERROR);
        }
        return true;
    }

    @Override
    public void removeLoginStatus() {
        jwtUtils.removeToken(request.getHeader(JWTConstant.HEAD_NAME));
    }

    @Override
    public void refreshAuth() {
        jwtUtils.refreshToken(request.getHeader(JWTConstant.HEAD_NAME));
    }
}




